ae2780
@@ -158,8 +158,11 @@
 import org.datanucleus.ClassLoaderResolver;
 import org.datanucleus.ClassLoaderResolverImpl;
 import org.datanucleus.NucleusContext;
+import org.datanucleus.api.jdo.JDOPersistenceManager;
 import org.datanucleus.api.jdo.JDOPersistenceManagerFactory;
 import org.datanucleus.store.rdbms.exceptions.MissingTableException;
+import org.datanucleus.store.scostore.Store;
+import org.datanucleus.util.WeakValueMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -8448,22 +8451,55 @@
private static void clearOutPmfClassLoaderCache(PersistenceManagerFactory pmf) {
     JDOPersistenceManagerFactory jdoPmf = (JDOPersistenceManagerFactory) pmf;
     NucleusContext nc = jdoPmf.getNucleusContext();
     try {
+      Field pmCache = pmf.getClass().getDeclaredField("pmCache");
+      pmCache.setAccessible(true);
+      Set<JDOPersistenceManager> pmSet = (Set<JDOPersistenceManager>)pmCache.get(pmf);
+      for (JDOPersistenceManager pm : pmSet) {
+        org.datanucleus.ExecutionContext ec = (org.datanucleus.ExecutionContext)pm.getExecutionContext();
+        if (ec instanceof org.datanucleus.ExecutionContextThreadedImpl) {
+          ClassLoaderResolver clr = ((org.datanucleus.ExecutionContextThreadedImpl)ec).getClassLoaderResolver();
+          clearClr(clr);
+        }
+      }
+      org.datanucleus.plugin.PluginManager pluginManager = jdoPmf.getNucleusContext().getPluginManager();
+      Field registryField = pluginManager.getClass().getDeclaredField("registry");
+      registryField.setAccessible(true);
+      org.datanucleus.plugin.PluginRegistry registry = (org.datanucleus.plugin.PluginRegistry)registryField.get(pluginManager);
+      if (registry instanceof org.datanucleus.plugin.NonManagedPluginRegistry) {
+        org.datanucleus.plugin.NonManagedPluginRegistry nRegistry = (org.datanucleus.plugin.NonManagedPluginRegistry)registry;
+        Field clrField = nRegistry.getClass().getDeclaredField("clr");
+        clrField.setAccessible(true);
+        ClassLoaderResolver clr = (ClassLoaderResolver)clrField.get(nRegistry);
+        clearClr(clr);
+      }
+      if (nc instanceof org.datanucleus.PersistenceNucleusContextImpl) {
+        org.datanucleus.PersistenceNucleusContextImpl pnc = (org.datanucleus.PersistenceNucleusContextImpl)nc;
+        org.datanucleus.store.types.TypeManagerImpl tm = (org.datanucleus.store.types.TypeManagerImpl)pnc.getTypeManager();
+        Field clrField = tm.getClass().getDeclaredField("clr");
+        clrField.setAccessible(true);
+        ClassLoaderResolver clr = (ClassLoaderResolver)clrField.get(tm);
+        clearClr(clr);
+        Field storeMgrField = pnc.getClass().getDeclaredField("storeMgr");
+        storeMgrField.setAccessible(true);
+        org.datanucleus.store.rdbms.RDBMSStoreManager storeMgr = (org.datanucleus.store.rdbms.RDBMSStoreManager)storeMgrField.get(pnc);
+        Field backingStoreField = storeMgr.getClass().getDeclaredField("backingStoreByMemberName");
+        backingStoreField.setAccessible(true);
+        Map<String, Store> backingStoreByMemberName = (Map<String, Store>)backingStoreField.get(storeMgr);
+        for (Store store : backingStoreByMemberName.values()) {
+          org.datanucleus.store.rdbms.scostore.BaseContainerStore baseStore = (org.datanucleus.store.rdbms.scostore.BaseContainerStore)store;
+          clrField = org.datanucleus.store.rdbms.scostore.BaseContainerStore.class.getDeclaredField("clr");
+          clrField.setAccessible(true);
+          clr = (ClassLoaderResolver)clrField.get(baseStore);
+          clearClr(clr);
+        }
+      }
       Field classLoaderResolverMap = AbstractNucleusContext.class.getDeclaredField(
           "classLoaderResolverMap");
       classLoaderResolverMap.setAccessible(true);
       Map<String,ClassLoaderResolver> loaderMap =
           (Map<String, ClassLoaderResolver>) classLoaderResolverMap.get(nc);
       for (ClassLoaderResolver clr : loaderMap.values()){
-        if (clr != null){
-          if (clr instanceof ClassLoaderResolverImpl){
-            ClassLoaderResolverImpl clri = (ClassLoaderResolverImpl) clr;
-            long resourcesCleared = clearFieldMap(clri,"resources");
-            long loadedClassesCleared = clearFieldMap(clri,"loadedClasses");
-            long unloadedClassesCleared = clearFieldMap(clri, "unloadedClasses");
-            LOG.debug("Cleared ClassLoaderResolverImpl: " +
-                resourcesCleared + "," + loadedClassesCleared + "," + unloadedClassesCleared);
-          }
-        }
+        clearClr(clr);
       }
       classLoaderResolverMap.set(nc, new HashMap<String, ClassLoaderResolver>());
       LOG.debug("Removed cached classloaders from DataNucleus NucleusContext");
@@ -8472,13 +8508,25 @@
private static void clearOutPmfClassLoaderCache(PersistenceManagerFactory pmf) {
     }
   }
 
+  private static void clearClr(ClassLoaderResolver clr) throws Exception {
+    if (clr != null){
+      if (clr instanceof ClassLoaderResolverImpl){
+        ClassLoaderResolverImpl clri = (ClassLoaderResolverImpl) clr;
+        long resourcesCleared = clearFieldMap(clri,"resources");
+        long loadedClassesCleared = clearFieldMap(clri,"loadedClasses");
+        long unloadedClassesCleared = clearFieldMap(clri, "unloadedClasses");
+        LOG.debug("Cleared ClassLoaderResolverImpl: " +
+            resourcesCleared + "," + loadedClassesCleared + "," + unloadedClassesCleared);
+      }
+    }
+  }
   private static long clearFieldMap(ClassLoaderResolverImpl clri, String mapFieldName) throws Exception {
     Field mapField = ClassLoaderResolverImpl.class.getDeclaredField(mapFieldName);
     mapField.setAccessible(true);
 
     Map<String,Class> map = (Map<String, Class>) mapField.get(clri);
     long sz = map.size();
-    map.clear();
+    mapField.set(clri, Collections.synchronizedMap(new WeakValueMap()));
     return sz;
   }
 
